#!/bin/sh
#
# halt          This file is executed by init when it goes into runlevel
#               0 (halt) or runlevel 6 (reboot). It kills all processes,
#               unmounts file systems and then either halts or reboots.
#
# Author:       Miquel van Smoorenburg, <miquels@drinkel.nl.mugnet.org>
#               Modified for RHS Linux by Damien Neil
#

NOLOCALE=1
. /etc/init.d/functions

UMOUNT="umount"
[ ! -w /etc ] && UMOUNT="umount -n"

action() {
   echo -n "$1 "
   shift
   if [ "$BOOTUP" = "color" ]; then
      "$@" && echo_success || echo_failure
   else
      "$@"
   fi
   echo
}

halt_crypto() {
    fnval=0
    while read dst src key; do
	[ -z "$dst" -o "${dst#\#}" != "$dst" ] && continue
        if [ -b "/dev/mapper/$dst" ]; then
            if /sbin/dmsetup info "$dst" | grep -q '^Open count: *0$'; then
                action $"Stopping disk encryption for $dst" /sbin/cryptsetup remove "$dst"
            else
                fnval=1
            fi
        fi
    done < /etc/crypttab
    return $fnval
}

# See how we were called.
case "$0" in
   *halt)
	message=$"Halting system..."
	command="/sbin/halt"
	;;
   *reboot)
	message=$"Please stand by while rebooting the system..."
	command="/sbin/reboot"
	kexec_command="/sbin/kexec"
	;;
   *)
	echo $"$0: call me as 'halt' or 'reboot' please!"
	exit 1
	;;
esac
case "$1" in
   *start)
   	;;
   *)
	echo $"Usage: $0 {start}"
	exit 1
	;;
esac

# Kill all processes.
[ "${BASH+bash}" = bash ] && enable kill

action $"Sending all processes the TERM signal..." /sbin/killall5 -15
sleep 5
action $"Sending all processes the KILL signal..."  /sbin/killall5 -9

# Write to wtmp file before unmounting /var
/sbin/halt -w

# Save mixer settings, here for lack of a better place.
grep -q "\(alsa\)" /proc/devices
if [ $? = 0 -a -x /usr/sbin/alsactl ]; then
   action $"Saving mixer settings" alsactl store
fi

# Save random seed
touch /var/lib/random-seed
chmod 600 /var/lib/random-seed
action $"Saving random seed: " dd if=/dev/urandom of=/var/lib/random-seed count=1 bs=512 2>/dev/null

# Sync the system clock.
ARC=0
SRM=0
UTC=0

if [ -f /etc/sysconfig/clock ]; then
   . /etc/sysconfig/clock

   # convert old style clock config to new values
   if [ "${CLOCKMODE}" = "GMT" ]; then
      UTC=true
   elif [ "${CLOCKMODE}" = "ARC" ]; then
      ARC=true
   fi
fi

CLOCKDEF=""
CLOCKFLAGS="$CLOCKFLAGS --systohc"

case "$UTC" in
   yes|true)
	CLOCKFLAGS="$CLOCKFLAGS -u";
	CLOCKDEF="$CLOCKDEF (utc)";
	;;
   no|false)
	CLOCKFLAGS="$CLOCKFLAGS --localtime";
	CLOCKDEF="$CLOCKDEF (localtime)";
	;;
esac

case "$ARC" in
   yes|true)
	CLOCKFLAGS="$CLOCKFLAGS -A";
	CLOCKDEF="$CLOCKDEF (arc)";
	;;
esac
case "$SRM" in
   yes|true)
	CLOCKFLAGS="$CLOCKFLAGS -S";
	CLOCKDEF="$CLOCKDEF (srm)";
	;;
esac

[ -x /sbin/hwclock ] && action $"Syncing hardware clock to system time" /sbin/hwclock $CLOCKFLAGS

# Try to unmount tmpfs filesystems to avoid swapping them in.  Ignore failures.
tmpfs=$(awk '$2 ~ /^\/($|proc|dev)/ { next; }
	     $3 == "tmpfs" { print $2; }' /proc/mounts | sort -r)
[ -n "$tmpfs" ] && fstab-decode $UMOUNT $tmpfs 2>/dev/null

# Turn off swap, then unmount file systems.
[ -f /proc/swaps ] && SWAPS=`awk '! /^Filename/ { print $1 }' /proc/swaps`
if [ -n "$SWAPS" ]; then
    action $"Turning off swap: " swapoff $SWAPS
    for dst in $SWAPS; do
	if [[ "$dst" =~ "^/dev/mapper" ]] \
	    && [ "$(dmsetup status "$dst" | cut -d ' ' -f 3)" = crypt ]; then
	    backdev=$(/sbin/cryptsetup status "$dst" \
		| awk '$1 == "device:" { print $2 }')
	    /sbin/cryptsetup remove "$dst"
	fi
    done
fi

[ -x /sbin/quotaoff ] && action $"Turning off quotas: " /sbin/quotaoff -aug

# Unmount file systems, killing processes if we have to.
# Unmount loopback stuff first
__umount_loopback_loop

# Unmount RPC pipe file systems
__umount_loop '$3 ~ /^rpc_pipefs$/ || $3 ~ /^rpc_svc_gss_pipefs$/ {print $2}' \
    /proc/mounts \
    $"Unmounting pipe file systems: " \
    $"Unmounting pipe file systems (retry): " \
    -f

LANG=C __umount_loop '$2 ~ /^\/$|^\/proc|^\/dev/{next}
	$3 == "tmpfs" || $3 == "proc" {print $2 ; next}
	/(loopfs|autofs|nfs|cifs|smbfs|ncpfs|sysfs|^none|^\/dev\/ram|^\/dev\/root$)/ {next}
	{print $2}' /proc/mounts \
	$"Unmounting file systems: " \
	$"Unmounting file systems (retry): " \
	-f

[ -f /proc/bus/usb/devices ] && $UMOUNT /proc/bus/usb

[ -f /etc/crypttab ] && halt_crypto

# remove the crash indicator flag
rm -f /.autofsck

# Try all file systems other than root, essential filesystems and RAM disks,
# one last time.
awk '$2 !~ /\/(|dev|proc|selinux)$/ && $1 !~ /^\/dev\/ram/ { print $2 }' \
    /proc/mounts | sort -r | \
  while read line; do
    fstab-decode $UMOUNT -f $line
done

if [ -x /sbin/halt.local ]; then
   /sbin/halt.local
fi

# Remount read only anything that's left mounted.
# echo $"Remounting remaining filesystems readonly"
mount | awk '{ print $3 }' | while read line; do
    fstab-decode mount -n -o ro,remount $line
done

# Now halt or reboot.
echo $"$message"
if [ -f /fastboot ]; then
 echo $"On the next boot fsck will be skipped."
elif [ -f /forcefsck ]; then
 echo $"On the next boot fsck will be forced."
fi

if [ "$command" = /sbin/halt -a -r /etc/ups/upsmon.conf -a -f /etc/killpower -a -f /etc/sysconfig/ups ] ; then
	. /etc/sysconfig/ups
	if [ "$SERVER" = "yes" -a "$MODEL" = "upsdrvctl" ] ; then
		/sbin/upsdrvctl shutdown
	elif [ "$SERVER" = "yes" -a "$MODEL" != "NONE" -a -n "$MODEL" -a -n "$DEVICE" ] ; then
		$MODEL $OPTIONS_HALT -k $DEVICE
	fi
fi

# First, try kexec. If that fails, fall back to rebooting the old way.
[ -n "$kexec_command" ] && $kexec_command -e -x >& /dev/null

HALTARGS="-d"
[ "$INIT_HALT" != "HALT" ] && HALTARGS="$HALTARGS -p"

exec $command $HALTARGS
